package com.ctsi.commons.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtil {

	/**
	 * 替换
	 * 
	 * @param mainString
	 *            原始
	 * @param oldString
	 *            被替换
	 * @param newString
	 *            新的
	 * @return mainString 替换后
	 */
	public static String replaceString(String mainString, String oldString, String newString) {
		if (mainString == null) {
			return null;
		}
		if (oldString == null || oldString.length() == 0) {
			return mainString;
		}
		if (newString == null) {
			newString = "";
		}

		int i = mainString.lastIndexOf(oldString);

		if (i < 0)
			return mainString;

		StringBuilder mainSb = new StringBuilder(mainString);

		while (i >= 0) {
			mainSb.replace(i, i + oldString.length(), newString);
			i = mainString.lastIndexOf(oldString, i - 1);
		}
		return mainSb.toString();
	}

	/**
	 * 建立分割的单一string
	 * 
	 * @param list
	 *            a list of strings to join
	 * @param delim
	 *            分割符号 no delimiter)
	 * @return a 去掉分割符号的 String
	 */
	public static String join(List<String> list, String delim) {
		if (UtilValidate.isEmpty(list)) {
			return null;
		}
		StringBuilder buf = new StringBuilder(list.size() << 3);
		Iterator<String> i = list.iterator();

		while (i.hasNext()) {
			buf.append(i.next());
			if (i.hasNext()) {
				buf.append(delim);
			}
		}
		return buf.toString();
	}

	public static String join(String str, String delim, String next) {
		if (UtilValidate.isEmpty(str))
			return next;
		if (str.endsWith(delim))
			return str + next;
		else
			return str + delim + next;
	}

	/**
	 * 转化String 到 map
	 * 
	 * @param s
	 *            String 格式 ({n1=v1, n2=v2})
	 * @return new Map
	 */
	public static Map<String, String> toMap(String s) {
		Map<String, String> newMap = new HashMap<String, String>();
		if (s.startsWith("{") && s.endsWith("}")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				String[] nv = entry.split("\\=");
				newMap.put(nv[0], nv[1]);
			}
		} else {
			throw new IllegalArgumentException("String is not from Map.toString()");
		}

		return newMap;
	}

	/**
	 * 转化为list
	 * 
	 * 
	 * @param s
	 *            list toString 的格式
	 * @return new List
	 */
	public static List<String> toList(String s) {
		List<String> newList = new ArrayList<String>();
		if (s.startsWith("[") && s.endsWith("]")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				newList.add(entry);
			}
		} else {
			throw new IllegalArgumentException("String is not from List.toString()");
		}

		return newList;
	}

	/**
	 * string转化为set
	 * 
	 * 
	 * @param s
	 *            set toString产生字符串的格式
	 * @return new List
	 */
	public static Set<String> toSet(String s) {
		Set<String> newSet = new HashSet<String>();
		if (s.startsWith("[") && s.endsWith("]")) {
			s = s.substring(1, s.length() - 1);
			String[] entries = s.split("\\,\\s");
			for (String entry : entries) {
				newSet.add(entry);
			}
		} else {
			throw new IllegalArgumentException("String is not from Set.toString()");
		}

		return newSet;
	}

	/**
	 * 分割字符串
	 * 
	 * @param str
	 *            被分割字符串
	 * @param delim
	 *            分割符号
	 * @return
	 */
	public static List<String> split(String str, String delim) {
		List<String> splitList = null;
		StringTokenizer st = null;

		if (str == null)
			return splitList;

		if (delim != null)
			st = new StringTokenizer(str, delim);
		else
			st = new StringTokenizer(str);

		splitList = new ArrayList<String>();

		while (st.hasMoreTokens()) {
			splitList.add(st.nextToken());
		}

		return splitList;
	}

	/**
	 * 为增加单引号
	 * 
	 * @param list
	 *            List of String(s) to quote.
	 */
	public static List<String> quoteStrList(List<String> list) {
		List<String> tmpList = new ArrayList<String>(list.size());

		Iterator<String> i = list.iterator();

		while (i.hasNext()) {
			tmpList.add("'" + i.next() + "'");
		}
		return tmpList;
	}

	public static String listtoStr(final List<Object> list) {
		if (list == null || list.size() == 0)
			return "";

		StringBuilder result = new StringBuilder();
		for (int i = 0; i < list.size(); i++) {

			if (i > 0) {
				result.append(',');
			}

			result.append(list.get(i));

		}
		return result.toString();
	}

	public static String listtoStrIn(final List<String> list, boolean isparam) {
		if (list == null || list.size() == 0)
			return "()";

		StringBuilder result = new StringBuilder("(");

		for (int i = 0; i < list.size(); i++) {
			if (i > 0)
				result.append(',');
			if (isparam) {
				result.append('?');
			} else {
				result.append('\'');
				result.append(list.get(i));
				result.append('\'');
			}

		}
		result.append(')');
		return result.toString();
	}

	public static String arraytoStrIn(final String[] list, boolean isparam) {
		if (list == null || list.length == 0)
			return "()";

		StringBuilder result = new StringBuilder(list.length << 3);
		result.append('(');
		for (int i = 0; i < list.length; i++) {
			if (i > 0)
				result.append(',');
			if (isparam) {
				result.append('?');
			} else {
				result.append('\'');
				result.append(list[i]);
				result.append('\'');
			}

		}
		result.append(')');
		return result.toString();
	}

	/**
	 * String转化为map String 格式 key=value splite key=value
	 * 
	 * @param str
	 * @param trim
	 * @param splite
	 * @return
	 */
	public static Map<String, String> strToMap(String str, boolean trim, String splite) {

		if (UtilValidate.isEmpty(str))
			return new HashMap<String, String>();
		Map<String, String> decodedMap = new HashMap<String, String>();
		List<String> elements = split(str, splite);
		setToMap(decodedMap, elements, trim);
		return decodedMap;

	}

	public static void setToMap(Map<String, String> decodedMap, Iterable<String> source, boolean trim) {
		for (String s : source) {

			List<String> e = split(s, "=");

			if (e.size() != 2) {
				continue;
			}
			String name = e.get(0);
			String value = e.get(1);
			if (trim) {
				if (name != null) {
					name = name.trim();
				}
				if (value != null) {
					value = value.trim();
				}
			}

			decodedMap.put(name, value);
		}

	}

	/**
	 * 从String建立map
	 * 
	 * @param str
	 *            转换的字符串
	 * @param trim
	 *            分割符号
	 * @return a Map of name/value pairs
	 */
	public static Map<String, String> strToMap(String str, boolean trim) {
		return strToMap(str, trim, "|");

	}

	/**
	 * 转化 name/value 格式为Map
	 * 
	 * @param str
	 *            需要转化的String
	 * @return a Map of name/value pairs
	 */
	public static Map<String, String> strToMap(String str) {
		return strToMap(str, false);
	}

	/**
	 * 转化map为String,只转化其中的String类型
	 * 
	 * @param map
	 *            需要转化的map
	 * @return String 转化的String
	 */
	public static String mapToStr(Map<?, ?> map) {
		if (map == null)
			return null;
		StringBuilder buf = new StringBuilder();
		Set<?> keySet = map.keySet();
		Iterator<?> i = keySet.iterator();
		boolean first = true;

		while (i.hasNext()) {
			Object key = i.next();
			Object value = map.get(key);

			if (!(key instanceof String) || !(value instanceof String))
				continue;

			if (first)
				first = false;
			else
				buf.append('|');

			buf.append((String) key);
			buf.append('=');
			buf.append((String) value);
		}
		return buf.toString();
	}

	/**
	 * 两个list转化为map
	 * 
	 * @param keys
	 *            List of keys
	 * @param values
	 *            List of values
	 * @return 转化的map
	 * @throws IllegalArgumentException
	 *             参数null或者数量不等
	 */
	public static Map<Object, Object> createMap(List<?> keys, List<?> values) {
		if (keys == null || values == null || keys.size() != values.size()) {
			throw new IllegalArgumentException("Keys and Values cannot be null and must be the same size");
		}
		Map<Object, Object> newMap = new HashMap<Object, Object>();
		for (int i = 0; i < keys.size(); i++) {
			newMap.put(keys.get(i), values.get(i));
		}
		return newMap;
	}

	/**
	 * 确定路径以路径分割符号开始，并且不以分割符号结束
	 * 
	 * @param prefix
	 * @return
	 */
	public static String cleanUpPathPrefix(String prefix) {
		if (prefix == null || prefix.length() == 0)
			return "";

		StringBuilder cppBuff = new StringBuilder(prefix.replace('\\', '/'));

		if (cppBuff.charAt(0) != '/') {
			cppBuff.insert(0, '/');
		}
		if (cppBuff.charAt(cppBuff.length() - 1) == '/') {
			cppBuff.deleteCharAt(cppBuff.length() - 1);
		}
		return cppBuff.toString();
	}

	/**
	 * 删除所有空格
	 * 
	 * @param str
	 * @return
	 */
	public static String removeSpaces(String str) {
		return removeRegex(str, "[\\ ]");
	}

	public static int convertChar(char c) {
		if ('0' <= c && c <= '9') {
			return c - '0';
		} else if ('a' <= c && c <= 'f') {
			return c - 'a' + 0xa;
		} else if ('A' <= c && c <= 'F') {
			return c - 'A' + 0xa;
		} else {
			throw new IllegalArgumentException("Invalid hex character: [" + c + "]");
		}
	}

	/**
	 * 首字母大写
	 * 
	 * @param str
	 * @return
	 */
	public static String upperFirstChar(String str) {
		if (UtilValidate.isEmpty(str))
			return str;
		if (str.length() == 1)
			return str.toUpperCase();
		StringBuilder sb = new StringBuilder(str);

		sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
		return sb.toString();
	}

	/**
	 * 首字母小写
	 * 
	 */
	public static String lowerFirstChar(String str) {
		if (str == null)
			return null;
		if (str.length() <= 1)
			return str.toLowerCase();
		StringBuilder sb = new StringBuilder(str);

		sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
		return sb.toString();
	}

	public static String htmlSpecialChars(String html, boolean doubleQuotes, boolean singleQuotes, boolean insertBR) {
		if (UtilValidate.isEmpty(html))
			return html;
		html = StringUtil.replaceString(html, "&", "&amp;");
		html = StringUtil.replaceString(html, "<", "&lt;");
		html = StringUtil.replaceString(html, ">", "&gt;");
		if (doubleQuotes) {
			html = StringUtil.replaceString(html, "\"", "&quot;");
		}
		if (singleQuotes) {
			html = StringUtil.replaceString(html, "'", "&#039;");
		}
		if (insertBR) {
			html = StringUtil.replaceString(html, "\n", "<br>");
		}

		return html;
	}

	public static String decodeHtmlSpecialChars(String html, boolean doubleQuotes, boolean singleQuotes, boolean insertBR) {
		if (UtilValidate.isEmpty(html))
			return html;
		html = StringUtil.replaceString(html, "&amp;", "&");
		html = StringUtil.replaceString(html, "&lt;", "<");
		html = StringUtil.replaceString(html, "&gt;", ">");
		if (doubleQuotes) {
			html = StringUtil.replaceString(html, "&quot;", "\"");
		}
		if (singleQuotes) {
			html = StringUtil.replaceString(html, "&#039;", "'");
		}
		if (insertBR) {
			html = StringUtil.replaceString(html, "<br>", "\n");
		}

		return html;
	}

	/**
	 * 对HTML代码进行解码
	 */
	public static String htmlDecoding(String encodedHtml) {

		return decodeHtmlSpecialChars(encodedHtml, true, false, false);
	}

	/**
	 * 对HTML代码进行编码
	 */
	public static String htmlEncoding(String strHtml) {
		return htmlSpecialChars(strHtml, true, false, false);
	}

	/**
	 * 对字符串进行URL解码
	 */
	public static String URLDecoding(String encodedUrl) {
		if (encodedUrl == null)
			return null;
		try {
			return URLDecoder.decode(encodedUrl, UtilFile.Charset_UTF8);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 对字符串进行URL编码
	 */
	public static String URLEncoding(String url) {
		if (url == null)
			return null;
		try {
			return URLEncoder.encode(url, UtilFile.Charset_UTF8);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 编码是否有效
	 * 
	 * @param text
	 * @return
	 */
	public static boolean Utf8codeCheck(String text) {
		String sign = "";
		if (text.startsWith("%e"))
			for (int p = 0; p != -1;) {
				p = text.indexOf("%", p);
				if (p != -1)
					p++;
				sign += p;
			}
		return sign.equals("147-1");
	}

	/**
	 * 是否Utf8Url编码
	 * 
	 * @param text
	 * @return
	 */
	public static boolean isUtf8Url(String text) {
		text = text.toLowerCase();
		int p = text.indexOf("%");
		if (p != -1 && text.length() - p > 9) {
			text = text.substring(p, p + 9);
		}
		return Utf8codeCheck(text);
	}

	/**
	 * // * 删除非数字字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String removeNonNumeric(String str) {
		return removeRegex(str, "[\\D]");
	}

	/** Removes all numbers from str */
	public static String removeNumeric(String str) {
		return removeRegex(str, "[\\d]");
	}

	/**
	 * @param str
	 * @param regex
	 *            删除的正则表达式
	 */
	private static String removeRegex(String str, String regex) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		return matcher.replaceAll("");
	}

	public static final String byte2hex(byte[] b, char split) {
		return byte2hex(b, Character.valueOf(split)).toUpperCase();
	}

	public static final String byte2hex(final byte[] b, final Character split) {
		if (b == null || b.length == 0)
			return "";
		StringBuilder hs = new StringBuilder(100);
		String stmp;
		if (split != null) {
			for (int n = 0; n < b.length; n++) {
				stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
				if (stmp.length() == 1)
					hs.append('0').append(stmp);
				else
					hs.append(stmp);

				if (n < b.length - 1)
					hs.append(split);

			}
		} else {
			for (int n = 0; n < b.length; n++) {
				stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
				if (stmp.length() == 1)
					hs.append('0').append(stmp);
				else
					hs.append(stmp);

			}
		}

		return hs.toString();
	}

	public static String byte2hex(byte[] b) {
		return byte2hex(b, Character.valueOf(':')).toUpperCase();
	}

	private static char toHex(int nibble) {
		return hexDigit[(nibble & 0xF)];
	}

	/** A table of hex digits */
	private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	/**
	 * java String 转化为\\u形式的字符串
	 * 
	 * @param theString
	 *            需要转化的串
	 * @param escapeSpace
	 *            是否编码空格
	 * @param escapeUnicode
	 *            是否编码Unicode
	 * @return
	 */
	public static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) {
		int len = theString.length();
		int bufLen = len * 2;
		if (bufLen < 0) {
			bufLen = Integer.MAX_VALUE;
		}
		StringBuilder outBuffer = new StringBuilder(bufLen);

		for (int x = 0; x < len; x++) {
			char aChar = theString.charAt(x);
			// Handle common case first, selecting largest block that
			// avoids the specials below
			if ((aChar > 61) && (aChar < 127)) {
				if (aChar == '\\') {
					outBuffer.append('\\');
					outBuffer.append('\\');
					continue;
				}
				outBuffer.append(aChar);
				continue;
			}
			switch (aChar) {
			case ' ':
				if (x == 0 || escapeSpace)
					outBuffer.append('\\');
				outBuffer.append(' ');
				break;
			case '\t':
				outBuffer.append('\\');
				outBuffer.append('t');
				break;
			case '\n':
				outBuffer.append('\\');
				outBuffer.append('n');
				break;
			case '\r':
				outBuffer.append('\\');
				outBuffer.append('r');
				break;
			case '\f':
				outBuffer.append('\\');
				outBuffer.append('f');
				break;
			case '=': // Fall through
			case ':': // Fall through
			case '#': // Fall through
			case '!':
				outBuffer.append('\\');
				outBuffer.append(aChar);
				break;
			default:
				if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode) {
					outBuffer.append('\\');
					outBuffer.append('u');
					outBuffer.append(toHex((aChar >> 12) & 0xF));
					outBuffer.append(toHex((aChar >> 8) & 0xF));
					outBuffer.append(toHex((aChar >> 4) & 0xF));
					outBuffer.append(toHex(aChar & 0xF));
				} else {
					outBuffer.append(aChar);
				}
			}
		}
		return outBuffer.toString();
	}

	/**
	 * \\u形式的转化为java 字符串
	 * 
	 * @param in
	 *            需要转化的串
	 * @param off
	 *            开始位置
	 * @param len
	 *            长度
	 * @param convtBuf
	 *            中间缓存空间
	 * @return
	 */
	public static String loadConvert(char[] in, int off, int len, char[] convtBuf) {
		if (convtBuf.length < len) {
			int newLen = len * 2;
			if (newLen < 0) {
				newLen = Integer.MAX_VALUE;
			}
			convtBuf = new char[newLen];
		}
		char aChar;
		char[] out = convtBuf;
		int outLen = 0;
		int end = off + len;

		while (off < end) {
			aChar = in[off++];
			if (aChar == '\\') {
				aChar = in[off++];
				if (aChar == 'u') {
					// Read the xxxx
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = in[off++];
						switch (aChar) {
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							value = (value << 4) + aChar - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							value = (value << 4) + 10 + aChar - 'a';
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							value = (value << 4) + 10 + aChar - 'A';
							break;
						default:
							throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
						}
					}
					out[outLen++] = (char) value;
				} else {
					if (aChar == 't')
						aChar = '\t';
					else if (aChar == 'r')
						aChar = '\r';
					else if (aChar == 'n')
						aChar = '\n';
					else if (aChar == 'f')
						aChar = '\f';
					out[outLen++] = aChar;
				}
			} else {
				out[outLen++] = aChar;
			}
		}
		return new String(out, 0, outLen);
	}

	public static final String concatString(String str1, String str2) {

		return str1.concat(str2);
	}

	public static final String concatString(String str1, String str2, String str3) {

		StringBuilder result = new StringBuilder(str1.length() + str2.length() + str3.length());
		result.append(str1);
		result.append(str2);
		result.append(str3);
		return result.toString();
	}

	public static final String concatString(String... str) {
		if (UtilValidate.isEmpty(str)) {
			return "";
		}
		if (str.length == 1) {
			return str[0];
		}
		StringBuilder result = new StringBuilder(str.length << 4);
		for (String s : str) {
			result.append(s);
		}
		return result.toString();
	}

	public final static String trim(String s) {
		if (s == null)
			return s;
		return s.trim();
	}

	public static final boolean equals(final String cs1, final String cs2) {
		if (cs1 == cs2) {
			return true;
		}
		if (cs1 == null || cs2 == null) {
			return false;
		}

		return cs1.equals(cs2);

	}
}
